package com.meiyuetao.myt.partner.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

import lab.s2jh.bpm.service.ActivitiService;
import lab.s2jh.core.dao.BaseDao;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.core.service.Validation;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.meiyuetao.myt.core.constant.VoucherStateEnum;
import com.meiyuetao.myt.core.constant.VoucherTypeEnum;
import com.meiyuetao.myt.core.service.VoucherNumGenerateService;
import com.meiyuetao.myt.customer.service.SmsLogService;
import com.meiyuetao.myt.finance.dao.BizTradeUnitDao;
import com.meiyuetao.myt.finance.service.AccountInOutService;
import com.meiyuetao.myt.md.dao.CommodityDao;
import com.meiyuetao.myt.md.dao.CommodityVaryPriceDao;
import com.meiyuetao.myt.md.entity.Commodity;
import com.meiyuetao.myt.md.entity.CommodityVaryPrice;
import com.meiyuetao.myt.partner.dao.DistributeDeliveryDao;
import com.meiyuetao.myt.partner.entity.DistributeDelivery;
import com.meiyuetao.myt.partner.entity.DistributeDelivery.DistributeDeliveryStatusEnum;
import com.meiyuetao.myt.partner.entity.DistributeDeliveryDetail;
import com.meiyuetao.myt.purchase.dao.SupplierDao;
import com.meiyuetao.myt.sale.dao.BoxOrderDao;
import com.meiyuetao.myt.sale.dao.BoxOrderDetailCommodityDao;
import com.meiyuetao.myt.sale.dao.BoxOrderDetailDao;
import com.meiyuetao.myt.sale.dao.SaleDeliveryDetailDao;
import com.meiyuetao.myt.sale.entity.BoxOrderDetail;
import com.meiyuetao.myt.stock.dao.StorageLocationDao;
import com.meiyuetao.myt.stock.entity.CommodityStock;
import com.meiyuetao.myt.stock.entity.StockInOut;
import com.meiyuetao.myt.stock.entity.StorageLocation;
import com.meiyuetao.myt.stock.service.CommodityStockService;
import com.meiyuetao.myt.stock.service.StockInOutService;

@Service
@Transactional
public class DistributeDeliveryService extends BaseService<DistributeDelivery, Long> {

    @Autowired
    private DistributeDeliveryDao distributeDeliveryDao;
    @Autowired
    private CommodityStockService commodityStockService;
    @Autowired
    private StorageLocationDao storageLocationDao;
    @Autowired
    private CommodityDao commodityDao;
    @Autowired
    private BoxOrderDao boxOrderDao;
    @Autowired
    private BoxOrderDetailDao boxOrderDetailDao;
    @Autowired
    private BoxOrderDetailCommodityDao boxOrderDetailCommodityDao;
    @Autowired
    private BoxOrderDao commodityVaDao;
    @Autowired
    private CommodityVaryPriceDao commodityVaryPriceDao;
    @Autowired
    private BizTradeUnitDao bizTradeUnitDao;
    @Autowired
    private SmsLogService smsLogService;

    @Autowired
    private AccountInOutService accountInOutService;
    @Autowired
    private VoucherNumGenerateService voucherNumGenerateService;
    @Autowired
    private SaleDeliveryDetailDao saleDeliveryDetailDao;
    @Autowired
    private StockInOutService stockInOutService;
    @Autowired
    private SupplierDao supplierDao;

    @Autowired(required = false)
    private ActivitiService activitiService;

    @Override
    protected BaseDao<DistributeDelivery, Long> getEntityDao() {
        return distributeDeliveryDao;
    }

    private CommodityStock findCommodityCommodityStock(DistributeDeliveryDetail ddd) {
        Commodity commodity = commodityDao.findOne(ddd.getCommodity().getId());
        StorageLocation storageLocation = storageLocationDao.findOne(ddd.getStorageLocation().getId());
        String batchNo = ddd.getBatchNo();
        CommodityStock commodityStock = commodityStockService.findBy(commodity, storageLocation, batchNo);
        Validation.isTrue(commodityStock != null, "须先初始化维护库存数据: 商品=[" + commodity.getDisplay() + "],库存地=[" + storageLocation.getDisplay() + "],批次号=[" + batchNo + "]");
        Validation.isTrue(commodityStock.getCostPrice() != null && commodityStock.getCostPrice().doubleValue() > 0, "成本价格无效: 商品=[" + commodity.getDisplay() + "],库存地=["
                + storageLocation.getDisplay() + "],批次号=[" + batchNo + "],成本价=[" + commodityStock.getCostPrice() + "]");
        return commodityStock;
    }

    private void saveDetails(DistributeDelivery entity) {
        BigDecimal commodityCostAmount = BigDecimal.ZERO;
        for (DistributeDeliveryDetail sdd : entity.getDistributeDeliveryDetails()) {
            sdd.setDistributeDelivery(entity);
            CommodityStock commodityStock = findCommodityCommodityStock(sdd);
            sdd.setCostPrice(commodityStock.getCostPrice());
            sdd.setCostAmount(commodityStock.getCostPrice().multiply(sdd.getQuantity()));
            commodityCostAmount = commodityCostAmount.add(sdd.getCostAmount());
        }

        entity.setCommodityCostAmount(commodityCostAmount);
        entity.setTotalCostAmount(commodityCostAmount.add(entity.getLogisticsAmount() == null ? BigDecimal.ZERO : entity.getLogisticsAmount()));
    }

    public void bpmCreate(DistributeDelivery entity, Map<String, Object> variables) {
        saveDetails(entity);
        distributeDeliveryDao.save(entity);
        activitiService.startProcessInstanceByKey("BPM_DISTRIBUTE_DELIVERY", entity);
    }

    public void bpmUpdate(DistributeDelivery entity, String taskId, Map<String, Object> variables) {
        Validation.isTrue(entity.getRedwordDate() == null, "销售单已经红冲");
        saveDetails(entity);
        distributeDeliveryDao.save(entity);
        activitiService.completeTask(taskId, variables);
    }

    /**
     * 供工作流在所有审批完成后的回调接口
     */
    public void bpmAuditPost(DistributeDelivery entity) {
        entity.setAuditDate(new Date());
        entity.setLastOperationSummary(entity.buildLastOperationSummary("审核完结"));
        entity.setDistributeDeliveryStatus(DistributeDeliveryStatusEnum.S30AUDITTED);
        for (DistributeDeliveryDetail ddd : entity.getDistributeDeliveryDetails()) {

            StockInOut stockInOut = buildDefaultStockInOut(entity, ddd);
            stockInOut.setDiffSalingQuantity(ddd.getQuantity());
            stockInOut.setOperationSummary("提交销售单锁定库存量");
            stockInOutService.saveCascade(stockInOut);

            // 更新商品最近销售价格
            if (!Boolean.TRUE.equals(ddd.getGift())) {
                // 新增行项时商品对象为Web层构建的空数据对象，需要DAO基于主键查询加载处理
                Commodity commodity = commodityDao.findOne(ddd.getCommodity().getId());
                CommodityVaryPrice commodityVaryPrice = commodity.getCommodityVaryPrice();
                commodityVaryPrice.setLastSalePrice(ddd.getPrice());
                commodityVaryPriceDao.save(commodityVaryPrice);
            }
        }
        distributeDeliveryDao.save(entity);
    }

    private StockInOut buildDefaultStockInOut(DistributeDelivery distributeDelivery, DistributeDeliveryDetail ddd) {
        CommodityStock commodityStock = findCommodityCommodityStock(ddd);
        StockInOut stockInOut = new StockInOut(distributeDelivery.getVoucher(), ddd.getSubVoucher(), VoucherTypeEnum.XS, commodityStock);
        return stockInOut;
    }

    public DistributeDelivery doSave(DistributeDelivery entity) {
        return distributeDeliveryDao.save(entity);
    }

    /**
     * 红冲配货单
     * 
     * @param entity
     */
    public void chargeAgainst(DistributeDelivery entity) {
        Validation.isTrue(entity.getRedwordDate() == null, "配货单已经红冲");
        Validation.isTrue(entity.getDeliveryTime() == null, "已发货的不能红冲，只能走退货流程");
        // 移除工作流实例
        activitiService.deleteProcessInstanceByEntity(entity);
        entity.setRedwordDate(new Date());
        entity.setVoucherState(VoucherStateEnum.REDW);
        entity.setLastOperationSummary(entity.buildLastOperationSummary("红冲"));
        distributeDeliveryDao.save(entity);
        // 克隆创建红冲对象，只复制主对象，明细行项数据不复制
        DistributeDelivery redwordTarget = new DistributeDelivery();
        String[] copyIgnoreProperties = ArrayUtils.addAll(entity.retriveCommonProperties(), new String[] { "distributeDeliveryDetails", "voucher", "voucherDate" });
        BeanUtils.copyProperties(entity, redwordTarget, copyIgnoreProperties);
        redwordTarget.setVoucherDate(new Date());
        redwordTarget.setVoucher("R" + entity.getVoucher());
        distributeDeliveryDao.save(redwordTarget);

        // 处理库存红冲退回
        stockInOutService.redword(entity.getVoucher(), VoucherTypeEnum.XS, redwordTarget.getVoucher());

        if (entity.getDeliveryTime() != null) {
            BoxOrderDetail boxOrderDetail = entity.getBoxOrderDetail();
            if (boxOrderDetail != null) {
                boxOrderDetail.setLogisticsNo(null);
                boxOrderDetail.setLogisticsName(null);
                boxOrderDetail.setDeliveryFinishTime(null);
                boxOrderDetailDao.save(boxOrderDetail);
            }
        }

        // 处理财务红冲退回
        accountInOutService.redword(entity.getVoucher(), VoucherTypeEnum.XS, redwordTarget.getVoucher());
    }
}
